package cool.houge.infra.tx;

import io.avaje.inject.aop.AspectProvider;
import io.avaje.inject.aop.Invocation;
import io.avaje.inject.aop.MethodInterceptor;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.lang.reflect.Method;

/**
 * @author KK (kzou227@qq.com)
 */
@Singleton
public class TransactionAspect implements AspectProvider<Transactional>, MethodInterceptor {

  private final TxOps txOps;

  @Inject
  public TransactionAspect(TxOps txOps) {
    this.txOps = txOps;
  }

  @Override
  public MethodInterceptor interceptor(Method method, Transactional aspectAnnotation) {
    return this;
  }

  @Override
  public void invoke(Invocation invocation) throws Throwable {
    var method = invocation.method();
    var rtype = method.getReturnType();
    if (rtype == Mono.class) {
      var p = txOps.tx((Mono<?>) invocation.invoke());
      invocation.result(p);
    } else if (rtype == Flux.class) {
      var p = txOps.tx((Flux<?>) invocation.invoke());
      invocation.result(p);
    } else {
      // exception
    }
  }
}
